<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" xml:lang="es" xmlns="http://www.w3.org/1999/xhtml" lang="es"><head>

	
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta name="keywords" content="Capítulo 3: ¡Qué aburrido! yo quiero interactuar,Capítulo 2.- ¡Esta vivo! ¡vivoooooo! ¡JAJAJA!,Capítulo 4: Soy un artista... ¡No me coartes!,Gimp,Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets">
<link rel="shortcut icon" href="http://doc.ubuntu-es.org/favicon.ico">
<link rel="search" type="application/opensearchdescription+xml" href="http://doc.ubuntu-es.org/opensearch_desc.php" title="doc.ubuntu-es (Español)">
<link title="Creative Commons" type="application/rdf+xml" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=creativecommons" rel="meta">
<link rel="copyright" href="http://creativecommons.org/licenses/by-sa/3.0/">
		<title>Capítulo 3: ¡Qué aburrido! yo quiero interactuar - doc.ubuntu-es</title>
		<style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/skins/monobook/main.css?42b"; /*]]>*/</style>
		<link rel="stylesheet" type="text/css" media="print" href="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/commonPrint.css">
		<link rel="stylesheet" type="text/css" media="handheld" href="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/handheld.css">
		<!--[if lt IE 5.5000]><style type="text/css">@import "/skins/monobook/IE50Fixes.css?42b";</style><![endif]-->
		<!--[if IE 5.5000]><style type="text/css">@import "/skins/monobook/IE55Fixes.css?42b";</style><![endif]-->
		<!--[if IE 6]><style type="text/css">@import "/skins/monobook/IE60Fixes.css?42b";</style><![endif]-->
		<!--[if IE 7]><style type="text/css">@import "/skins/monobook/IE70Fixes.css?42b";</style><![endif]-->
		<!--[if lt IE 7]><script type="text/javascript" src="/skins/common/IEFixes.js?42b"></script>
		<meta http-equiv="imagetoolbar" content="no" /><![endif]-->
		
		<script type="text/javascript">/*<![CDATA[*/
var skin = "monobook";
var stylepath = "/skins";
var wgArticlePath = "/$1";
var wgScriptPath = "";
var wgServer = "http://doc.ubuntu-es.org";
var wgCanonicalNamespace = "";
var wgCanonicalSpecialPageName = false;
var wgNamespaceNumber = 0;
var wgPageName = "Capítulo_3:_¡Qué_aburrido!_yo_quiero_interactuar";
var wgTitle = "Capítulo 3: ¡Qué aburrido! yo quiero interactuar";
var wgArticleId = "1873";
var wgIsArticle = true;
var wgUserName = null;
var wgUserLanguage = "es";
var wgContentLanguage = "es";
var wgBreakFrames = false;
var wgCurRevisionId = "11597";
/*]]>*/</script>
                
		<script type="text/javascript" src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/wikibits.js"><!-- wikibits js --></script>
		<script type="text/javascript" src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/index.php"><!-- site js --></script>
		<style type="text/css">/*<![CDATA[*/
@import "/index.php?title=MediaWiki:Common.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
@import "/index.php?title=MediaWiki:Monobook.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
@import "/index.php?title=-&action=raw&gen=css&maxage=18000";
/*]]>*/</style>
		<!-- Head Scripts -->
		<script type="text/javascript" src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/ajax.js"></script>
<script src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-3100124-1";
urchinTracker();
</script>
	</head><body class="mediawiki ns-0 ltr page-Capítulo_3_¡Qué_aburrido_yo_quiero_interactuar">
	<div id="globalWrapper">
		<div id="column-content">
	<div id="content">
		<a name="top" id="top"></a>
				<h1 class="firstHeading">Capítulo 3: ¡Qué aburrido! yo quiero interactuar</h1>
		<div id="bodyContent">
			<h3 id="siteSub">De doc.ubuntu-es</h3>
			<div id="contentSub"></div>
									<div id="jump-to-nav">Saltar a <a href="#column-one">navegación</a>, <a href="#searchInput">búsqueda</a></div>			<!-- start content -->
			<table id="toc" class="toc" summary="Tabla de contenidos"><tbody><tr><td><div id="toctitle"><h2>Tabla de contenidos</h2> <span class="toctoggle">[<a href="javascript:toggleToc()" class="internal" id="togglelink">esconder</a>]</span></div>
<ul>
<li class="toclevel-1"><a href="#Introducci.C3.B3n"><span class="tocnumber">1</span> <span class="toctext">Introducción</span></a></li>
<li class="toclevel-1"><a href="#Manejo_de_eventos"><span class="tocnumber">2</span> <span class="toctext">Manejo de eventos</span></a>
<ul>
<li class="toclevel-2"><a href="#Evento_cerrar"><span class="tocnumber">2.1</span> <span class="toctext">Evento cerrar</span></a>
<ul>
<li class="toclevel-3"><a href="#Evento_cerrar_del_men.C3.BA"><span class="tocnumber">2.1.1</span> <span class="toctext">Evento cerrar del menú</span></a></li>
<li class="toclevel-3"><a href="#Evento_cerrar_de_la_barra_de_t.C3.ADtulo"><span class="tocnumber">2.1.2</span> <span class="toctext">Evento cerrar de la barra de título</span></a></li>
</ul>
</li>
</ul>
</li>
<li class="toclevel-1"><a href="#Creaci.C3.B3n_de_una_ProgressBar:"><span class="tocnumber">3</span> <span class="toctext">Creación de una ProgressBar:</span></a>
<ul>
<li class="toclevel-2"><a href="#Barra_de_progreso:"><span class="tocnumber">3.1</span> <span class="toctext">Barra de progreso:</span></a></li>
<li class="toclevel-2"><a href="#Controles_de_la_barra:"><span class="tocnumber">3.2</span> <span class="toctext">Controles de la barra:</span></a></li>
</ul>
</li>
<li class="toclevel-1"><a href="#Manejo_de_eventos_.28II.29:"><span class="tocnumber">4</span> <span class="toctext">Manejo de eventos (II):</span></a>
<ul>
<li class="toclevel-2"><a href="#Evento_de_.22Start.22:"><span class="tocnumber">4.1</span> <span class="toctext">Evento de "Start":</span></a></li>
<li class="toclevel-2"><a href="#Evento_de_.22Stop.22:"><span class="tocnumber">4.2</span> <span class="toctext">Evento de "Stop":</span></a>
<ul>
<li class="toclevel-3"><a href="#Cola_de_eventos"><span class="tocnumber">4.2.1</span> <span class="toctext">Cola de eventos</span></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</td></tr></tbody></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "mostrar"; var tocHideText = "esconder"; showTocToggle(); } </script>
<a name="Introducci.C3.B3n"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=1" title="Editar sección: Introducción">editar</a>]</span> <span class="mw-headline"> Introducción </span></h2>
<p>En este capítulo comenzaremos a preparar la interfaz para que pueda
interactuar con el usuario, e introduciremos (ya que son la misma cosa)
los eventos. Este será un paso de gigante, ya que nos permitirá
introducir un par de órdenes esenciales para todo código que vaya a
entrar en bucles largos, para ello nos crearemos una barra de progreso
que no hara más que rellenarse y vaciarse, y unos botones de start y
stop.
</p><p>Sería interesante introducir una pantalla para imprimir cosas, pero eso parece ya demasiado para este capítulo.
</p><p>Así que nuestro plan de trabajo será tal que:
</p>
<ul><li> Plan de trabajo del capítulo 3:
<ul><li> Manejo de eventos (I): <br>Crearemos nuestra primera tabla de eventos, y aprenderemos a manejar nuestros primeros eventos
<ul><li> Evento cerrar:
<ul><li> Evento cerrar del menú: <br>Crearemos la respuesta al evento de cerrar a través del menú "file/exit..."
</li><li> Evento cerrar de la barra de título: <br>Crearemos la respuesta al evento de cerrar a través de la "X" de la barra de título.
</li></ul>
</li></ul>
</li><li> Creación de una ProgressBar: <br>Crearemos una Barra de progresos, y sus controles.
<ul><li> Barra de progreso: <br>Haciendo uso de la documentación encontraremos cual es el objeto que buscamos, y lo implementaremos.
</li><li> Controles de la barra: <br>Crearemos una pequeña barra de herramientas para controlar a esta barra de progreso.
</li></ul>
</li><li> Manejo de eventos (II): <br>Crearemos todo lo necesario para manejar la barra de control.
<ul><li> Evento de "Start": <br>El que nos permitirá poner a funcionar la barra de progreso.
</li><li> Evento de "Stop": <br>El que nos permitirá parar la barra.
<ul><li> Cola de eventos: <br>No impacientarse, veremos que es lo que ocurre...
</li></ul>
</li></ul>
</li></ul>
</li></ul>
<p><br>
</p>
<a name="Manejo_de_eventos"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=2" title="Editar sección: Manejo de eventos">editar</a>]</span> <span class="mw-headline"> Manejo de eventos </span></h2>
<p>En la programación con interfaz gráfica, el manejo de eventos se
vuelve la llave que abre todas las puertas, y es que nos permite hacer
cosas que en un principio solo se podrían hacer acudiendo a los
multiprocesos. La idea básicamente consistirá en lo siguiente, cada uno
de los elementos de la interfaz gráfica, cada vez que se actúe sobre
él, emitirá un evento, de una clase o de otra dependiendo la acción que
se haya llevado (porque evidentemente no deberá comportarse igual
cuando cambies su tamaño, que cuando lo cierres). Ese evento lo
anclaremos mediante tablas de eventos, a un método (método = función)
que ejecutará las acciones pertinentes (las que nosotros deseemos para
esa actuación).
</p><p><br>
</p>
<a name="Evento_cerrar"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=3" title="Editar sección: Evento cerrar">editar</a>]</span> <span class="mw-headline"> Evento cerrar </span></h3>
<p>Para manejar nuestro primer evento, ya dejamos preparado un menú tal que "<b>file/exit...</b>".
Este evento será muy interesante, ya que deberá compartir sus acciones
con el evento de cerrar presionando sobre la "X" de la ventana. Eso nos
enseñará dos cosas, como manejar eventos que necesiten ID, y como
manejar los que no lo necesiten (que no tienen ninguna diferencia, pero
que nos enseñará que en algunos casos, los eventos no necesitan ID), y
lo que es más importante, nos enseñará a hacer las cosas bien (para no
duplicar código).
</p>
<a name="Evento_cerrar_del_men.C3.BA"></a><h4><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=4" title="Editar sección: Evento cerrar del menú">editar</a>]</span> <span class="mw-headline"> Evento cerrar del menú </span></h4>
<p>Bien, así que recuperamos nuestro trabajo donde lo dejamos, y acudimos presto a abrir <b>"topframe.h"</b>. Las tablas de eventos hay que predeclararlas, y eso se hace en nuestra cabecera, simplemente añadiendo las siguientes líneas:
</p>
<pre> class TopFrame&nbsp;: public wxFrame
 {
 public:
     TopFrame(wxString Title = _T("Welcome to wxWidgets"));
 <b>private:</b>
     <b>// any class wishing to process wxWidgets events must use this macro</b>
     <b>DECLARE_EVENT_TABLE()</b>
 };
</pre>
<p>Lo cierto es que nuestros eventos serán una cosa privada (private:),
que sólo la clase en cuestión debe manejar, ya no sólo porque es
intuitivamente lo lógico, sino porque nos puede ahorrar algunos
problemillas.
</p><p>Bueno, hemos declarado la tabla de eventos, ahora vamos a
declarar un método para controlar el evento. Llamémoslo por ejemplo
"OnQuit", y lo pondremos como privado, ya que será el que maneje el
evento... No obstante, puede ocurrir que más tarde algún elemento pueda
tener la necesidad de cerrar el programa, así que la gestión de cierre
deberá ser algo publico, así que crearemos otro método llamado "Quit",
que será realmente el que nos cierre la aplicación (todo esto tendrá un
transfondo mucho más interesante, que entenderemos más adelante).
También necesitamos saber que tipo de evento manejaremos, así que en
nuestra API (a partir de ahora denominaremos así al wx.chm) buscamos
wxMenu, y en el apartado "Event handling", nos da este evento:
"wxCommandEvent", que será el que habremos de usar...
</p><p>Así pues, nuestra cabecera deberá modificarse así:
</p>
<pre> class TopFrame&nbsp;: public wxFrame
 {
 public:
     TopFrame(wxString Title = _T("Welcome to wxWidgets"));    
     <b>void Quit();</b>
 private:
     <b>void OnQuit(wxCommandEvent&amp; event);</b>    
     // any class wishing to process wxWidgets events must use this macro
     DECLARE_EVENT_TABLE()
 };
</pre>
<p>Donde efectivamente llevamos a cabo todas las operaciones que planteabamos...
</p><p>El siguiente punto sin duda debería ser implementar todo esto, así que abrimos <b>"topframe.cpp"</b>, y lo primero de todo añadimos la tabla de eventos:
</p>
<pre> <b>BEGIN_EVENT_TABLE(TopFrame, wxFrame)  
 END_EVENT_TABLE()</b>
 
 TopFrame::TopFrame(wxString Title)
&nbsp;: wxFrame(NULL, wxID_ANY, Title)
 {
   <i>(...)</i>
</pre>
<p>Ahora recuperamos nuestra documentación, justo en el lugar donde la
dejamos, y nos encontramos que el macro en la tabla de eventos es
"EVT_MENU", pero necesitamos saber como funciona, así que lo buscamos,
y nos encontramos "wxCommandEvent", lo abrimos, y alli esta: <b>"EVT_MENU(id, func) "</b>
</p>
<ul><li> id: Ya lo conocemos, le pusimos wxID_EXIT.
</li><li> func: La función a la queremos anclarlo la hemos declarado como OnQuit.
</li></ul>
<p>Así que la tabla de eventos quedará de la forma:
</p>
<pre> BEGIN_EVENT_TABLE(TopFrame, wxFrame)
     <b>EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)</b>
 END_EVENT_TABLE()
</pre>
<p>Ahora debemos implementar nuestros dos métodos, empezemos con el que
maneja el evento (OnQuit), para ello, al final del archivo añadimos las
siguientes líneas:
</p>
<pre> void TopFrame::OnQuit(wxCommandEvent&amp; WXUNUSED(event))
 {
 }
</pre>
<p>Como no queremos sacrale más partido a este evento, pues con saber
que se ha emitido la orden de cerrar nos es suficiente, ponemos como
entrada "wxCommandEvent&amp; WXUNUSED(event)". No actuaremos así por
ejemplo cuando manejemos el ratón, pues necesitaremos información sobre
donde estaba, o que botón apretó.
</p><p>Bueno, este método lo único que hará será llamar a la función que realmente gestiona el cierre:
</p>
<pre> void TopFrame::OnQuit(wxCommandEvent&amp; WXUNUSED(event))
 {
     <b>Quit();</b>
 }
</pre>
<p>Con esta argucia hemos arreglado un problema interesante, pues
imaginemos que algún otro objeto, o algún otro método quisieran cerrar
la aplicación, de ser el gestor el anterior método, para llamarle sería
necesario generar un evento, pues necesitariamos ese parámetro, pero
ahora van a poder llamar a Quit(), y listos.
</p>
<ul><li> Esto se puede hacer de muchas maneras, una sería por ejemplo
poner un evento por defecto, tal y como hicimos con el título de
TopFrame, no obstante, esta manera me parece más legible y elegante.
</li></ul>
<p>Ahora toca, casi a la fuerza, implementar nuestro método "Quit", así que nuevamente al final de archivo añadimos:
</p>
<pre> void TopFrame::Quit()
 {
 }
</pre>
<p>Y este método lo único que habrá de hacer bserá cerrar la aplicación:
</p>
<pre> void TopFrame::Quit()
 {
     <b>// true is to force the frame to close
     Close(true);</b>
 }
</pre>
<p>Esa orden que hemos añadido lo que hace es crear un evento de
cerrar, que es un evento que tiene la peculiaridad de tener una función
ya asociada que se encarga de cerrarlo por nosotros, pero en breves
momentos cambiaremos esa situación a nuestro favor.
</p><p>Bueno, ya podemos hacer alguna prueba, compilamos, y
ejecutamos. Vamos al menú "file", y seleccionamos "Exit Alt-F4". ¡Y se
cierra! ¡Lo hemos logrado!
</p><p>Ya sabemos crear menús, y anclarlos a eventos que apuntaran a
los métodos que nos interese, pero vamos a seguir rizando el rizo...
</p>
<a name="Evento_cerrar_de_la_barra_de_t.C3.ADtulo"></a><h4><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=5" title="Editar sección: Evento cerrar de la barra de título">editar</a>]</span> <span class="mw-headline"> Evento cerrar de la barra de título </span></h4>
<p>Bueno, hasta el momento nos las hemos apañado para que nuestro "Exit
Alt-F4" sea capaz de cerrar la aplicación, y como el botoncito de
cerrar de la barra de título ya lo tenía implementado, pues
efectivamente, en primera instancia habríamos terminado. Pero
supongamos que nuestro programa puede estar manejando algun archivo, o
requiere, al cerrar, borrar una serie de archivos temporales (algo muy
típico por otra parte), o que por ejemplo queramos que el programa
pregunte si queremos guardar anters de salir (más típico todavia). En
la concepción actual, podríamos meterlo en la función Quit(), pero
entonces al darle a cerrar en la barra de título no funcionaría,
necesitamos un nuevo evento, y un método asociado a él.
</p><p>Así que lo primero es encontrar información de lo que buscamos,
para ello vamos a nuestra API, y buscamos "close event", e
inmediatamente nos aparece "wxCloseEvent", así que lo ojeamos, y nos da
la solución: "EVT_CLOSE(func)".
</p><p>Pues bien, ya tenemos lo que necesitamos para empezar, y por tanto abrimos <b>"topframe.h"</b> para añadir el siguiente método:
</p>
<pre> class TopFrame&nbsp;: public wxFrame
 {
 public:
     TopFrame(wxString Title = _T("Welcome to wxWidgets"));
 
     void Quit();
 private:
     void OnQuit(wxCommandEvent&amp; event);
     <b>void OnQuitX(wxCloseEvent&amp; event);</b>
     // any class wishing to process wxWidgets events must use this macro
     DECLARE_EVENT_TABLE()
 };
</pre>
<p>Y ahora añadimos a la tabla de eventos en <b>"topfrmae.cpp"</b>:
</p>
<pre> BEGIN_EVENT_TABLE(TopFrame, wxFrame)
     EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)
     <b>EVT_CLOSE(TopFrame::OnQuitX)</b>
 END_EVENT_TABLE()
</pre>
<p>Y al final del archivo el método:
</p>
<pre> void TopFrame::OnQuitX(wxCloseEvent&amp; WXUNUSED(event))
 {
 }
</pre>
<p>La orden que permitirá el "escape" de la aplicación será la
destrucción de TpoFrame. A los locos de C++, en wxWidgets las cosas no
se destruyen con delete, sino que implementan una función llamada
Destroy() que hace todas las operaciones necesarias, y termina por
llamar a delete. Con esta premisa ya podemos completar nuestro método
de la forma:
</p>
<pre> void TopFrame::OnQuitX(wxCloseEvent&amp; WXUNUSED(event))
 {
     <b>/**************************************/
     /***** | Aqui todas las ordenes | *****/
     /***** |  previas al cerrado    | *****/
     /******V************************V******/
     // Por ejemplo
     // remove( "temporal.tmp" );
     /******A************************A******/
     /***** | Aqui todas las ordenes | *****/
     /***** |  previas al cerrado    | *****/
     /**************************************/  
 
     Destroy();</b>
 }
</pre>
<p>Compilar, y vereis como el programa se comporta exactamente igual.
</p>
<ul><li> Resumiendo... ¿Qué esta ocurriendo realmente? Pues lo que esta ocurriendo es lo siguiente:
<ul><li> Cuando se presiona el botón de cerrar de la barra de título:<br>1.- Se crea un wxCloseEvent<br>2.- Se acude a la tabla de eventos a este punto: <b>EVT_CLOSE(TopFrame::OnQuitX)</b><br>3.- Le redirecciona a la función: <b>TopFrame::OnQuitX</b><br>4.- Este método llama a: <b>Destroy();</b> Que destruye "TopFrame"<br>5.- Con TopFrame destruido el programa queda fuera de flujo, y por tanto se termina.<br>
</li><li> Cuando se usa la barra de menús:<br>1.- Se crea un wxCommandEvent<br>2.- Se acude a la tabla de eventos a este punto: <b>EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)</b><br>3.- Le redirecciona a la función:<b>TopFrame::OnQuit</b><br>4.- Esta llama a:<b>Close(true);</b><br>5.- Se genera un wxCloseEvent<br>6.- Se repite todo el punto anterior.
</li></ul>
</li></ul>
<p>¿A que ahora si veís claro por qué reservamos una función especial
para gestionar el cierre, y cómo funciona todo el sistema de eventos?
</p><p>¡Ya esta! ¿Qué más puedo necesitar saber? Pues aún hay algo que
te puedo enseñar (realmente el único conocimiento nuevo de verdad que
me queda por dar, ya que los próximos capítulos afianzarán ideas, y
mostrarán algunos elementos, pero no introducirán nada nuevo).
</p><p>Y para ver este nuevo conocimiento necesitamos algunas cosas, como pueda ser una progress bar, y unos controles...
</p>
<a name="Creaci.C3.B3n_de_una_ProgressBar:"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=6" title="Editar sección: Creación de una ProgressBar:">editar</a>]</span> <span class="mw-headline"> Creación de una ProgressBar: </span></h2>
<p>Ahora vamos plantearnos crear los lementos de la barra de progreso,
y de la barra de heramientas, y luego nos ocuparemos de manejarlos.
</p>
<a name="Barra_de_progreso:"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=7" title="Editar sección: Barra de progreso:">editar</a>]</span> <span class="mw-headline"> Barra de progreso: </span></h3>
<p>Bueno, lo primero que necesitaremos sin duda será una ProgressBar,
que seguro que wxWidgets ya sabe hacer, asi que vayamos a nuestra
querida API, y busquemos <b>progress bar</b>. Aparecerán ante nuestros ojos dos títulos interesantes, uno será <i>wxProgressDialog</i>,
que pudiera ser interesante (existen un montón de dialogos
prefabricados que siempre son una buena opción a tener en cuenta para
ahorrar trabajo), pero en nuestra concepción inicial no queríamos que
estuviera en un diálogo a parte, así que el título que de verdad nos va
a interesar es <i><b>wxGauge</b></i>, así que lo seleccionamos y lo ojeamos.
</p><p>Parece que no hay nada especial en cuanto a librerías a añadir,
ni en cuanto a eventos se refiere (parece un elemento de lo más simple,
y eso es bueno). Los estilos, pues principalmente el horizontal y el
vertical, porque existe otro, pero no nos lo recomienda, por no ser
compatible con la mayoría de plataformas, y como nosotros queremos que
sea multiplataforma, no lo usaremos...
</p><p>Así que este es un buen momento para recuperar nuestro trabajo
donde lo dejamos, y comenzaremos con la declaración de la ProgessBar en
<b>topframe.h</b>, así que lo abrimos, y la declaramos:
</p>
<pre> (...)
 public:
     TopFrame(wxString Title = _T("Welcome to wxWidgets"));
     void Quit();
     <b>wxGauge * ProgressBar;</b>
 private:
 (...)
</pre>
<p>Muy bien, ahora vamos a incluirla en nuestra TopFrame, para ello vamos a <b>topframe.cpp</b>, y añadimos un panel...
</p>
<ul><li> Para añadir elementos en los diálogos, se añaden sobre
paneles, que luego iremos colocando con los sizers, ya lo veremos, por
ahora nuestra ventana será de lo más feucho posible...
</li></ul>
<p>Para ello, al final del constructor hacemos lo siguiente:
</p>
<pre> (...)
 // Panel de herramientas (selector de vista)
 wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
 (...)
</pre>
<p>Donde estamos creando un panel, cuyo parente es this (TopFrame), sin
ningún ID, en el punto (0,0) (esquina superior izquierda), y que mide
256x32 pixels.
</p><p>En realidad no os estresseis demasiado con los tamaños, pues en
cuanto aprendamos a manejar los sizers, los tamaños casi siempre se
autoajustarán.
</p><p>Bueno, ya tenemos un panel sobre el que añadir la ProgressBar, así que construyámosla (justo después):
</p>
<pre> (...)
 // Panel de herramientas (selector de vista)
 wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));	
 <b>ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));</b>
 (...)
</pre>
<p>Donde hemos construido una barra de progreso cuyo parent es el panel
que acababamos de crear, sin nigún ID, con un rango de 100 (100%,
aunque esto no será habitual, lo normal es que el rango sea el valor
máximo que esparas alcanzar), a 3x3 pixeles de la esquina superiopr
izquierda, y con un tamaño tal que deja 3x3 pixeles hasta la esquina
inferior derecha.
</p><p>Compilamos y ejecutamos para ver que tal aspecto tiene... Bueno, pues ahi tenemos nuestra pequeña ProgressBar...
</p>
<a name="Controles_de_la_barra:"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=8" title="Editar sección: Controles de la barra:">editar</a>]</span> <span class="mw-headline"> Controles de la barra: </span></h3>
<p>Bueno, ahora vamos a crear una barra de herramientas para controlar
nuestra barra de progreso, para ello usaremos las dos imagenes
adjuntas: <a href="http://doc.ubuntu-es.org/Imagen:Wxstart.jpg" class="image" title="Imagen de start"><img src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/Wxstart.jpg" alt="Imagen de start" longdesc="/Imagen:Wxstart.jpg" height="15" width="16"></a> <a href="http://doc.ubuntu-es.org/Imagen:Wxstop.jpg" class="image" title="Imagen de stop"><img src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/Wxstop.jpg" alt="Imagen de stop" longdesc="/Imagen:Wxstop.jpg" height="15" width="16"></a>
</p><p>Colócalas en el mismo lugar donde tenmos los cpp y los h (en la carpeta learn0.<b><i>X</i></b>)
</p><p>Abrelas con el <a href="http://doc.ubuntu-es.org/Gimp" title="Gimp">gimp</a>, y guárdarlas en dos formatos diferentes, según estas instrucciones:
</p>
<pre> wxstart.jpg -&gt; start.bmp
 wxstart.jpg -&gt; start.xpm
 wxstop.jpg -&gt; stop.bmp
 wxstop.jpg -&gt; stop.xpm
</pre>
<p>Las .bmp las usaremos en windows en su día, y están bien como están,
pero las xpm, que son las que vamos a usar en linux, no están bien, y
hay que hacer un par de operaciones previas...
</p><p>Abriéndolas nuevamente con el <a href="http://www.gimp.org/" class="external text" title="http://www.gimp.org" rel="nofollow">gimp</a> (las xpm), vamos a introducirlas transparecia, para ello:
</p>
<ol><li> Vamos a "capa/transparencia/añadir canal alfa".
</li><li> Seleccionamos la herramienta <b>varita mágica</b>, y con ella seleccionamos todo el gris de la imagen, y le damos a "Supr". Las reguardamos con el mismo nombre, y salimos de <a href="http://www.gimp.org/" class="external text" title="http://www.gimp.org" rel="nofollow">gimp</a>.
</li></ol>
<p>Ocurre que el formato xpm no le hace mucha gracia a c++, y si
intentamos usarlas tal y como están, nos dará un montón de errores
(advertencias) por conversión obsoleta, así que las abrimos con <a href="http://www.guia-ubuntu.org/index.php?title=GEdit" class="external text" title="http://www.guia-ubuntu.org/index.php?title=GEdit" rel="nofollow">gedit</a>, o con cualquier editor de texto (lo que pasa que gedit nos va a permitir hacerlo como las balas), y hacemos lo siguiente:
</p>
<ol><li> Nos aseguramos que la segunda línea es como sigue para cada uno de nuestros archivos:<br>start.xpm -&gt; <b>static char * start_xpm[] = {</b><br>stop.xpm -&gt; <b>static char * stop_xpm[] = {</b>
</li><li> Escribimos al comienzo de la tercera línea lo siguiente:<br><b>(char *) </b>
</li><li> Vamos a "editar/reemplazar", y escribimos lo siguiente (comillas incluidas):<br>buscar: <b>",\n"</b><br>Reemplazar con: <b>",\n(char *) "</b><br>Y damos a Reemplazar todo.
</li><li> Reguardamos y salimos.
</li></ol>
<p>Bien, ya tenemos listas las imágenes, así que ya podemos empezar a crear nuestra barra de herramientas...
</p><p>Lo primero de todo es indicarle a nuestro programa que queremos
que tenga esas imágenes, para ello recurrimos a este par de órdenes al
comienzo de "<b>topframe.cpp</b>":
</p>
<pre> #include "start.xpm"
 #include "stop.xpm"
</pre>
<p>En priomera instancia, cuando se manejan imágenes, se puede actuar
de dos formas, una es teniendo las imágenes, en cualquier formato, en
un lugar conocido, y abriéndolas cada vez que las necesitemos, y la
otra es, incluyéndola en Linux, debiendo tener formato xpm, o en
Windows poniéndola en las resources, debiendo tener formato bmp.
</p><p>La primera forma tiene la ventaja de que el código medirá
menos, y compilará más rápido, la segunda tiene la ventaja de que las
imágenes forman parte del código, y así el programa no requiere que las
imágenes estén a parte, teniendo siempre que transportar ambas cosas.
</p><p>El como se manejan las imágenes de ésta innovadora segunda forma, lo vamos a ver en breve.
</p><p>Crear una barra de herramientas es muy parecido a crear el menú
(que por cierto, se puede tratar de ampliar después con estos dos
nuevos elementos), simplemente necesitaremos un par de ID para poder
manejar nuestros eventos, así que nos vamos a crear un nuevo archivo
llamado "<b>header.h</b>", y dentro escribiremos esto:
</p>
<pre> const int ID_START = wxID_HIGHEST+0;
 const int ID_STOP = wxID_HIGHEST+1;
</pre>
<p>Efectivamente, los ID no son más que enteros que declaramos como
constantes para poder tenerlos como constantes globales. Y para no
interferir con ningún ID de wxWidgets, usamos este ID que ya han
preparado ellos, llamado wxID_HIGHEST, que se corresponde con el ID más
alto sin usar (por eso +0, y no +1).
</p><p>Bueno, ahora regresamos a nuestro TopFrame, "<b>topframe.cpp</b>", y añadimos nuestra cabecera:
</p>
<pre> #include "header.h"
</pre>
<p>Bueno, esto marcha, conocidos nuestros ID, ya podemos crear nuestra
barra, para ello comenzamos creando, al final de "topframe.cpp", una
barra de herramientas con las siguientes órdenes (que como siempre
podeis en contrar en el API):
</p>
<pre>   //toolbar
   wxToolBar *toolBar = CreateToolBar();//nueva toolbar(constructor)
   toolBar-&gt;SetMargins(5, 5);//margenes
   toolBar-&gt;SetToolBitmapSize(wxSize(32, 32));//recoratara las imagenes a 32x32
</pre>
<p>Que hace exactamente lo que pone en los comentarios, y por último añadimos nuestros dos elementos y seteamos la toolBar:
</p>
<pre>   toolBar-&gt;AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
   toolBar-&gt;AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
 
   toolBar-&gt;Realize();
</pre>
<p>Como siempre, para saber que es lo que hace cada parámetro, recurrir
a la API. Aunque cabe destacar la imagen, que hemos introducido con:
</p>
<pre> wxBITMAP(start)
</pre>
<p>Cuando escribimos wxBITMAP(), el ya entiende que tratamos de
recurrir a un recurso incrustado en el código, a diferencia de
wxBitmap(), que es el constructor de la clase con el mismno nombre de
wxWidgets. Por otro lado, ponemos start, porque si recordais, cuando
editamos nuestro archivo start.xpm, yo insistí en que os ceriorárais de
que la segunda línea era tal y como sigue:
</p><p>static char * <b>start</b>_xpm[] = {
</p><p>Bien, compilamos y ejecutamos... ¡Y allí esta, nuestra barra de herramientas con nuestros dos botones!
</p>
<a name="Manejo_de_eventos_.28II.29:"></a><h2><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=9" title="Editar sección: Manejo de eventos (II):">editar</a>]</span> <span class="mw-headline"> Manejo de eventos (II): </span></h2>
<p>Con nuestra barra creada, por supuesto nuestro siguiente objetivo es
usar nuestros dos elementos. Ya veremos que el evento de start nos
vendrá rodado, pero el evento de stop nos dará una pequeña sorpresita.
</p>
<a name="Evento_de_.22Start.22:"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=10" title="Editar sección: Evento de &quot;Start&quot;:">editar</a>]</span> <span class="mw-headline"> Evento de "Start": </span></h3>
<p>Bueno, para nuestro evento de "start", lo único que necesitamos es una función que lo maneje, así que en el protegido de "<b>topframe.h</b>", añadimos una nueva función tal que:
</p>
<pre> private:
   void OnQuit(wxCommandEvent&amp; event);
   void OnQuitX(wxCloseEvent&amp; event);
   <b>void OnStart(wxCommandEvent&amp; event);</b>
   <b>void OnStop(wxCommandEvent&amp; event);</b>
   // any class wishing to process wxWidgets events must use this macro
   DECLARE_EVENT_TABLE()
</pre>
<p>Y una variable que controle cuando estamos corriendo, que la declararemos en el público como:
</p>
<pre> public:
   TopFrame(wxString Title = _T("Welcome to wxWidgets"));
   void Quit();
   wxGauge * ProgressBar;
   <b>bool m_running;</b>
</pre>
<p><br>Vamos declarando ya también la de "stop". Los eventos de la
barra de herramientas son exactamente iguales que los de la barra de
menús que ya hemos utilizado, es por eso que aparece
"wxCommandEvent&amp; event".
</p><p>Bien, acudamos a la tabla de eventos de nuestro "<b>topframe.cpp</b>", y añadamos un nuevo evento:
</p>
<pre> BEGIN_EVENT_TABLE(TopFrame, wxFrame)
   EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)
   <b>EVT_MENU(ID_START,  TopFrame::OnStart)</b>
   EVT_CLOSE(TopFrame::OnQuitX)
 END_EVENT_TABLE()
</pre>
<p>Y al final del constructor, demos la señal de que está parado:
</p>
<pre> (...)
   toolBar-&gt;AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
   <b>m_running = false;</b>
</pre>
<p>}
</p><p><br>
Y al final del todo añadamos la siguiente rutina:
</p>
<pre> void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
 {
     int i;
     m_running = true;
     while(m_running)
     {
         for(i=1;i&lt;=100;i++)
         {
             ProgressBar-&gt;SetValue(i);
         }
         for(i=99;i&gt;=2;i--)
         {
             ProgressBar-&gt;SetValue(i);
         }
     }
 }
</pre>
<p><br>Si recordáis como trabajamos con OnQuit(), lo mas puritano
hubiera sido crear otro método llamado start(), y OnStart() tan sólo
debería activar m_running, y llamar a start(), pero como siempre, las
normas están para saltárselas, y por ahorrar un poco de tiempo, pues
actuamos así, sin que sirva de precedente.
</p><p>Respecto a la función, pues sólo es un bucle que va desde 1
hasta 100 y vuelve, dando valores a nuestra progresbar, repitiéndose
hasta que m_running valga "false".
</p><p>Bien, con esto ya tenemos nuestro "start", pero antes de nada, pongamos nuestro "stop".
</p>
<a name="Evento_de_.22Stop.22:"></a><h3><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=11" title="Editar sección: Evento de &quot;Stop&quot;:">editar</a>]</span> <span class="mw-headline"> Evento de "Stop": </span></h3>
<p>Pues actuamos de forma absolutamente análoga, esto es, añadimos lo
siguiente en la tabla de eventos (recordando que ya habíamos
aprovechado para declarar nuestra función, luego huelga repetir ese
paso):
</p>
<pre> BEGIN_EVENT_TABLE(TopFrame, wxFrame)
   EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)
   EVT_MENU(ID_START,  TopFrame::OnStart)
   <b>EVT_MENU(ID_STOP,  TopFrame::OnStop)</b>
   EVT_CLOSE(TopFrame::OnQuitX)
 END_EVENT_TABLE()
</pre>
<p>Y añadimos al final nuestro método:
</p>
<pre> void TopFrame::OnStop(wxCommandEvent&amp; WXUNUSED(event))
 {
     m_running = false;
 }
</pre>
<p>Absolutamente simplón, que lo único que hace es establecer una señal de parado, para que OnStart termine su bucle.
</p><p>Bien, comnpilamos y ejecutamos... (Y seguimos leyendo, que te adelanto que van a existir problemas)
</p><p>¡Algo va mal! ¡No puedo pararlo! ¡La barra no se actualiza!.
Bien, vuelve a code::blocks, y usa el botón rojo con un aspa blanca
para detener el código.
</p>
<a name="Cola_de_eventos"></a><h4><span class="editsection">[<a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit&amp;section=12" title="Editar sección: Cola de eventos">editar</a>]</span> <span class="mw-headline"> Cola de eventos </span></h4>
<p>Bien, el primer problema a corregir es que no podemos parar el
código, esto se debe a que, aunque efectivamente al presionar cualquier
botón se genera un evento, este evento no se procesa nunca, ya que
nuestro código esta enfrascado en un bucle sin fin, así que parece
estar claro ¿no?, tenemos que pedirle a nuestro código que procese los
evento que se generen dentro del bucle, eso se hace (buscando como
siempre en el API) con dos órdenes llamadas Pending() y Dispatch().
Pero claro, ambas órdenes forman parte de wxApp, luego necesitamos que
TopFrame conozca SampleApp (que es nuestra wxApp).
</p><p>Esto se puede hacer de otra forma, mucho más limpia, y bastante
más elegante, pero que no obstante, no nos da tanta potencia, y por
ello, ni tan siquiera la introduzco.
</p><p>Bien, el primer paso es cambiar nuestro "<b>topframe.h</b>", añadiendo a la entrada de datos del Constructor lo siguiente:
</p>
<pre>   TopFrame(<b>SampleApp * AApp</b>, wxString Title = _T("Welcome to wxWidgets"));
</pre>
<p>Y añadiendo una nueva variable privada (reitero, que no os estresse
demasiado lo de publico, protegido, o privado, tan solo es una cuestión
de limpieza, pero realmente es un poco indiferente):
</p>
<pre> (...)
 private:
</pre>
<p>	SampleApp * App;
</p>
<pre> (...)
</pre>
<p>Y lo implementamos en "<b>topframe.cpp</b>", empezando porque ahora nuestra clase hace uso de SampleApp, luego necesitamos su cabecera, así que añadimos lo siguiente:
</p>
<pre> (...)
 #include "stop.xpm"
 <b>#include "main.h"</b>
 #include "topframe.h"
 #include "header.h"
 (...)
</pre>
<p>Es fundamental el orden, ya que cuando incluyas "topframe.h", esta
ya debe conocer el contenido de "minimal.h" (es interesante probar a
cambiarlo, para ver como nos devulve un error de que SampleApp no esta
declarado). Este orden será necesario cambiarlo también en "main.cpp"
</p><p>Y por supuesto tenemos que cambiar el constructor:
</p>
<pre> TopFrame::TopFrame(<b>SampleApp * AApp</b>, wxString Title)
&nbsp;: wxFrame(NULL, wxID_ANY, Title)
 {
 	<b>App = AApp;</b>
 (...)
</pre>
<p>Donde efectivamente recibimos un SampleApp, e inmediatamente después lo volcamos sobre una variable nuestra.
</p><p>Lo único que resta para poder disfrutar nuestro SampleApp es mandarselo en "<b>main.cpp</b>", así que cambiamos la orden de la siguiente manera:
</p>
<pre> (...)
   frame = new TopFrame(<b>this,</b> _T("Welcome to wxWidgets!"));
 (...)
</pre>
<p>Y ya está, ya podemos usar a SampleApp en nuestra TopFrame.
</p><p>Bien, las órdenes que queremos usar se utilizan como sigue (en "<b>topframe.cpp</b>"):
</p>
<pre> void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
 {
     int i;
     <b>bool token_true;</b>
</pre>
<pre>     m_running = true;
</pre>
<pre>     while(m_running)
     {
         for(i=1;i&lt;=100;i++)
         {
             ProgressBar-&gt;SetValue(i);
         }
         for(i=99;i&gt;=2;i--)
         {
             ProgressBar-&gt;SetValue(i);
         }
         <b>while((TopFrame *) App-&gt;Pending())
         {
             token_true=(TopFrame *) App-&gt;Dispatch();
         }</b>
     }
 }
</pre>
<p>Efectivamente son unas órdenes un poco extravagantes, pero
nuevamente asumimos que se usan así, y no nos preocupamos más.
Efectivamente, declaramos un tolken_true, que realmente es una variable
basura, para dar coherencia de compilación. Y cada vez que la barra de
progreso haga un "release", nos dedicamos a procesar evento mientras
sigan existiendo evento pendientes.
</p><p>Compilamos y ejecutamos...
</p><p>¡Algo hace! Pero desde luego, el gra avance es que podemos detener el código.
</p><p>Nuestro siguiente problema es que la barra de progreso se
mantiene inmutable (o casi), como oir llover vamos. Esto se debe a que
aunque nosotros actualizamos la barra, esta requiere que sus eventos
sean procesados, luego la solución es la mar de simple, tan sólo
tenemos que poner nuestras órdenes de análisis de eventos en cada
iteración:
</p>
<pre> void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
 {
     int i;
     bool token_true;
 
     m_running = true;
 
     while(m_running)
     {
         for(i=1;i&lt;=100;i++)
         {
             ProgressBar-&gt;SetValue(i);
             <b>while((TopFrame *) App-&gt;Pending())
             {
                 token_true=(TopFrame *) App-&gt;Dispatch();
             }</b>
         }
         for(i=99;i&gt;=2;i--)
         {
             ProgressBar-&gt;SetValue(i);
             <b>while((TopFrame *) App-&gt;Pending())
             {
                 token_true=(TopFrame *) App-&gt;Dispatch();
             }</b>
         }
     }
 } 
</pre>
<p>Compilamos y ejecutamos... ¡Éxito rotundo! Si, aunque vaya a toda pastilla y no se vea del todo bien.
</p><p>Finalmente nuestros archivos han quedado así:
</p><p>header.h
</p>
<pre>const int ID_START = wxID_HIGHEST+0;
const int ID_STOP = wxID_HIGHEST+1;
</pre>
<p>main.h
</p>
<pre>class SampleApp&nbsp;: public wxApp
{
public:
	virtual bool OnInit();
};
</pre>
<p>main.cpp
</p>
<pre>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;
#include &lt;wx/wx.h&gt;
#include &lt;wx/string.h&gt;
#include "main.h"
#include "topframe.h"

/**********************************************************************/
/************** This function run the application         *************/
/************** can force some parameters too (p.ej size) *************/
/**********************************************************************/

IMPLEMENT_APP(SampleApp)

bool SampleApp::OnInit()
{
    TopFrame *frame;
    //frame = new TopFrame();
    frame = new TopFrame(this, _T("Welcome to wxWidgets!"));
    frame-&gt;Show(true);	//show the frame of application
	frame-&gt;Maximize();	//maximize the frame of application
	return true; //true == run the app
	//no delete!!! it's implement in destroy();
}
</pre>
<p>topframe.h
</p>
<pre>class TopFrame&nbsp;: public wxFrame
{
public:
    TopFrame(SampleApp * AApp, wxString Title = _T("Welcome to wxWidgets"));
    void Quit();
    wxGauge * ProgressBar;
    bool m_running;

protected:
    void OnQuit(wxCommandEvent&amp; event);
    void OnQuitX(wxCloseEvent&amp; event);
    void OnStart(wxCommandEvent&amp; event);
    void OnStop(wxCommandEvent&amp; event);
    // any class wishing to process wxWidgets events must use this macro
private:
	SampleApp * App;
    DECLARE_EVENT_TABLE()
};
</pre>
<p>topframe.cpp
</p>
<pre>#include &lt;math.h&gt;
#include &lt;stdio.h&gt;
#include &lt;wx/wx.h&gt;
#include &lt;wx/string.h&gt;
#include "start.xpm"
#include "stop.xpm"
#include "main.h"
#include "topframe.h"
#include "header.h"

BEGIN_EVENT_TABLE(TopFrame, wxFrame)
    EVT_MENU(wxID_EXIT,  TopFrame::OnQuit)
    EVT_MENU(ID_START,  TopFrame::OnStart)
    EVT_MENU(ID_STOP,  TopFrame::OnStop)
    EVT_CLOSE(TopFrame::OnQuitX)
END_EVENT_TABLE()

TopFrame::TopFrame(SampleApp * AApp, wxString Title)
: wxFrame(NULL, wxID_ANY, Title)
{
	App = AApp;

	//creamos un menu muy simple
	wxMenu *fileMenu = new wxMenu;
	fileMenu-&gt;Append(wxID_EXIT, _T("&amp;Exit\tAlt-F4"), _T("Termina el programa"));
	wxMenuBar *menuBar = new wxMenuBar();
	menuBar-&gt;Append(fileMenu, _T("&amp;File"));
	SetMenuBar(menuBar);

    // Panel de herramientas (selector de vista)
	wxPanel * ControlPanel = new wxPanel(this, wxID_ANY, wxPoint(0,0), wxSize(256, 32));
	ProgressBar = new wxGauge(ControlPanel, wxID_ANY, 100, wxPoint(3,3), wxSize(250,32));

    //toolbar
    wxToolBar *toolBar = CreateToolBar();//nueva toolbar(constructor)
    toolBar-&gt;SetMargins(5, 5);//margenes
    toolBar-&gt;SetToolBitmapSize(wxSize(32, 32));//recoratara las imagenes a 32x32

    toolBar-&gt;AddTool(ID_START, wxBITMAP(start), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
    toolBar-&gt;AddTool(ID_STOP, wxBITMAP(stop), wxNullBitmap, false, wxDefaultCoord, wxDefaultCoord, (wxObject *)NULL, _T("Start"), _T("Run the progress bar"));
  
    toolBar-&gt;Realize();

    m_running = false;
}

void TopFrame::OnQuit(wxCommandEvent&amp; WXUNUSED(event))
{
    Quit();
}

void TopFrame::Quit()
{
    // true is to force the frame to close
    Close(true);
}

void TopFrame::OnQuitX(wxCloseEvent&amp; WXUNUSED(event))
{
    /**************************************/
    /***** | Aqui todas las ordenes | *****/
    /***** |  previas al cerrado    | *****/
    /******V************************V******/
    // Por ejemplo
    // remove( "temporal.tmp" );
    /******A************************A******/
    /***** | Aqui todas las ordenes | *****/
    /***** |  previas al cerrado    | *****/
    /**************************************/


	Destroy();
}

void TopFrame::OnStart(wxCommandEvent&amp; WXUNUSED(event))
{
    int i;
    bool token_true;

    m_running = true;

    while(m_running)
    {
        for(i=1;i&lt;=100;i++)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
        }
        for(i=99;i&gt;=2;i--)
        {
            ProgressBar-&gt;SetValue(i);
            while((TopFrame *) App-&gt;Pending())
            {
                token_true=(TopFrame *) App-&gt;Dispatch();
            }
        }
    }
}

void TopFrame::OnStop(wxCommandEvent&amp; WXUNUSED(event))
{
    m_running = false;
}
</pre>
<p>Ahora si que se puede decir que no tengo nada más que enseñar, con
esto ya se puede uno lanzar al mundo de wxWidgets sin problemas, pero
de todas formas seguiremos rizando un poco más el rizo, añadiendo una
ventana para pintar, y algún diálogo, que nos sirvan para fijar ideas.
Pero eso será en próximos capítulos.
</p>
<table class="wikitable" align="center" border="1">

<tbody><tr>
<td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_2.-_%C2%A1Esta_vivo%21_%C2%A1vivoooooo%21_%C2%A1JAJAJA%21" title="Capítulo 2.- ¡Esta vivo! ¡vivoooooo! ¡JAJAJA!">Capítulo 2.- ¡Esta vivo! ¡vivoooooo! ¡JAJAJA!</a>
</td><td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/Nuestra_primera_interfaz_gr%C3%A1fica_con_CodeBlocks_y_wxWidgets" title="Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets">Nuestra primera interfaz gráfica con CodeBlocks y wxWidgets</a>
</td><td style="border: 2px solid rgb(139, 103, 58); padding: 5px; text-align: center; background-color: rgb(240, 226, 198); -moz-border-radius-topleft: 8px; -moz-border-radius-topright: 8px; -moz-border-radius-bottomright: 8px; -moz-border-radius-bottomleft: 8px; font-weight: bold;"> <a href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_4:_Soy_un_artista..._%C2%A1No_me_coartes%21" title="Capítulo 4: Soy un artista... ¡No me coartes!">Capítulo 4: Soy un artista... ¡No me coartes!</a>
</td></tr></tbody></table>

<!-- Saved in parser cache with key doc_u-es:pcache:idhash:1873-0!1!0!!es!2 and timestamp 20100214184724 -->
<div class="printfooter">
Obtenido de "<a href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar">http://doc.ubuntu-es.org/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar</a>"</div>
			<div id="catlinks"><p class="catlinks"><a href="http://doc.ubuntu-es.org/Especial:Categories" title="Especial:Categories">Categoría</a>: <span dir="ltr"><a href="http://doc.ubuntu-es.org/Categor%C3%ADa:Programaci%C3%B3n" title="Categoría:Programación">Programación</a></span></p></div>			<!-- end content -->
			<div class="visualClear"></div>
		</div>
	</div>
		</div>
		<div id="column-one">
	<div id="p-cactions" class="portlet">
		<h5>Vistas</h5>
		<div class="pBody">
			<ul>
						 <li id="ca-nstab-main" class="selected"><a title="Ver el artículo [alt-c]" accesskey="c" href="http://doc.ubuntu-es.org/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar">Artículo</a></li>
						 <li id="ca-talk" class="new"><a title="Discusión acerca del artículo [alt-t]" accesskey="t" href="http://doc.ubuntu-es.org/index.php?title=Discusi%C3%B3n:Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit">Discusión</a></li>
						 <li id="ca-edit"><a title="Puedes editar esta página. Por favor, usa el botón de previsualización antes de grabar. [alt-e]" accesskey="e" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=edit">Editar</a></li>
						 <li id="ca-history"><a title="Versiones anteriores de esta página y sus autores [alt-h]" accesskey="h" href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;action=history">Historial</a></li>
				</ul>
		</div>
	</div>
	<div class="portlet" id="p-personal">
		<h5>Herramientas personales</h5>
		<div class="pBody">
			<ul>
				<li id="pt-login"><a title="Te animamos a registrarte, aunque no es obligatorio [alt-o]" accesskey="o" href="http://doc.ubuntu-es.org/index.php?title=Especial:Userlogin&amp;returnto=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar">Registrarse/Entrar</a></li>
			</ul>
		</div>
	</div>
	<div title="Portada" class="portlet" id="p-logo">
		<a style="background-image: url(/skins/common/images/wiki.png);" href="http://doc.ubuntu-es.org/Documentaci%C3%B3n" title="Documentación"></a>
	</div>
	<script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
		<div class="portlet" id="p-navigation">
		<h5>Navegación</h5>
		<div class="pBody">
			<ul>
				<li id="n-mainpage"><a title="Visitar la Portada [alt-z]" accesskey="z" href="http://doc.ubuntu-es.org/Documentaci%C3%B3n">Documentación</a></li>
				<li title="Acerca del proyecto, qué puedes hacer, dónde encontrar información" id="n-portal"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Portal_de_la_comunidad">Portal de la comunidad</a></li>
				<li title="Información de contexto sobre acontecimientos actuales" id="n-currentevents"><a href="http://doc.ubuntu-es.org/Proyectos">Proyectos</a></li>
				<li id="n-recentchanges"><a title="La lista de cambios recientes en el wiki [alt-r]" accesskey="r" href="http://doc.ubuntu-es.org/Especial:Recentchanges">Cambios recientes</a></li>
				<li id="n-randompage"><a title="Cargar una página aleatoriamente [alt-x]" accesskey="x" href="http://doc.ubuntu-es.org/Especial:Random">Página aleatoria</a></li>
				<li title="El lugar para aprender" id="n-help"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Ayuda">Ayuda</a></li>
				<li title="Respáldanos" id="n-sitesupport"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Tareas">Tareas</a></li>
			</ul>
		</div>
	</div>
		<div id="p-search" class="portlet">
		<h5><label for="searchInput">Buscar</label></h5>
		<div id="searchBody" class="pBody">
			<form action="/Especial:Search" id="searchform"><div>
				<input id="searchInput" name="search" accesskey="f" type="text">
				<input name="go" class="searchButton" id="searchGoButton" value="Ir" type="submit">&nbsp;
				<input name="fulltext" class="searchButton" id="mw-searchButton" value="Buscar" type="submit">
			</div></form>
		</div>
	</div>
	<div class="portlet" id="p-tb">
		<h5>Herramientas</h5>
		<div class="pBody">
			<ul>
				<li id="t-whatlinkshere"><a title="Lista de todas las páginas del wiki que enlazan con ésta [alt-j]" accesskey="j" href="http://doc.ubuntu-es.org/Especial:Whatlinkshere/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar">Lo que enlaza aquí</a></li>
				<li id="t-recentchangeslinked"><a title="Cambios recientes en las páginas que enlazan con esta otra [alt-k]" accesskey="k" href="http://doc.ubuntu-es.org/Especial:Recentchangeslinked/Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar">Seguimiento de enlaces</a></li>
<li id="t-upload"><a title="Subir imágenes o archivos multimedia [alt-u]" accesskey="u" href="http://doc.ubuntu-es.org/Especial:Upload">Subir archivo</a></li>
<li id="t-specialpages"><a title="Lista de todas las páginas especiales [alt-q]" accesskey="q" href="http://doc.ubuntu-es.org/Especial:Specialpages">Páginas especiales</a></li>
				<li id="t-print"><a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;printable=yes">Versión para imprimir</a></li>				<li id="t-permalink"><a href="http://doc.ubuntu-es.org/index.php?title=Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar&amp;oldid=11597">Enlace permanente</a></li>			</ul>
		</div>
	</div>
		</div><!-- end of the left (by default at least) column -->
			<div class="visualClear"></div>
			<div id="footer">
				<div id="f-poweredbyico"><a href="http://www.mediawiki.org/"><img src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/poweredby_mediawiki_88x31.png" alt="Powered by MediaWiki"></a></div>
				<div id="f-copyrightico"><a href="http://creativecommons.org/licenses/by-sa/3.0/"><img src="Cap%C3%ADtulo_3:_%C2%A1Qu%C3%A9_aburrido%21_yo_quiero_interactuar_archivos/88x31.png" alt="Atribución-Licenciar Igual 3.0"></a></div>
			<ul id="f-list">
				<li id="lastmod"> Esta página fue modificada por última vez el 19:43, 16 dic 2008.</li>
				<li id="viewcount">Esta página ha sido visitada 1.808 veces.</li>
				<li id="copyright">El contenido está disponible bajo los términos de la <i><a href="http://creativecommons.org/licenses/by-sa/3.0/" class="external " title="http://creativecommons.org/licenses/by-sa/3.0/" rel="nofollow">Atribución-Licenciar Igual 3.0</a></i></li>
				<li id="privacy"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Pol%C3%ADtica_de_protecci%C3%B3n_de_datos" title="doc.ubuntu-es:Política de protección de datos">Política de protección de datos</a></li>
				<li id="about"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Acerca_de" title="doc.ubuntu-es:Acerca de">Acerca de doc.ubuntu-es</a></li>
				<li id="disclaimer"><a href="http://doc.ubuntu-es.org/doc.ubuntu-es:Limitaci%C3%B3n_general_de_responsabilidad" title="doc.ubuntu-es:Limitación general de responsabilidad">Aviso legal</a></li>
			</ul>
		</div>
		
	
		<script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>
</div>
<!-- Served by vaca in 0.392 secs. --></body></html>